<?php

namespace app\member\model;

use app\BaseModel;
use think\facade\Cache;
use think\Db;

use app\weixin\model\WeiXinUsersModel;
use app\distribution\model\DividendRoleModel;

//*------------------------------------------------------ */
//-- 会员表
/*------------------------------------------------------ */

class UsersModel extends BaseModel
{
    protected $table = 'users';
    protected $mkey = 'user_info_mkey_';
    public $pk = 'user_id';
    public $userId = 0;
    public static $checkIDCardStatus = ['0' => '未认证', '1' => '已认证', '2' => '审核中', '3' => '审核失败'];
    /*------------------------------------------------------ */
    //--  清除memcache
    /*------------------------------------------------------ */
    public function cleanMemcache($user_id)
    {
        Cache::rm($this->mkey . $user_id);
        Cache::rm($this->mkey . 'account_' . $user_id);
        Cache::rm('member_wallet_mkey_info' . $user_id);
    }

    /*------------------------------------------------------ */
    //-- 系统登陆后执行
    /*------------------------------------------------------ */
    public function doLogin($user_id)
    {
        if ($user_id < 1) return false;
        $share_token = input('share_token', '', 'trim');
        if (empty($share_token) == false) {
            $userInfo = $this->info($user_id);
            if ($userInfo['is_bind'] == 0) {
                $upData['pid'] = $this->getShareUser($share_token);
            }
        }
        $time = time();
        $upData['login_odd_num'] = 0;//登陆异常清空
        $upData['login_time'] = $time;
        $upData['login_ip'] = request()->ip();
        $upData['last_login_time'] = Db::raw('last_login_time=login_time');
        $upData['last_login_ip'] = Db::raw('last_login_ip=login_ip');
        $this->upInfo($user_id, $upData);
        $inLog['log_ip'] = $upData['login_ip'];
        $inLog['log_time'] = $time;
        $inLog['user_id'] = $user_id;
        $inLog['source'] = request()->header('source');
        (new LogLoginModel)->save($inLog);
        //判断订单模块是否存在
        if (class_exists('app\shop\model\OrderModel')) {
            //执行订单自动签收
            (new \app\shop\model\OrderModel)->autoSign($user_id);
            (new \app\shop\model\CartModel)->loginUpCart($user_id);//更新购物车
        }
        $token = getAppToken();
        $appTokenKey = getAppTokenKey($token);
        Cache::set('uniappLogin_' . $appTokenKey, $user_id, 3600);
        return $token;
    }
    /*------------------------------------------------------ */
    //-- 会员退出
    /*------------------------------------------------------ */
    public function logout()
    {
        $token = request()->header('Token');
        if (empty($token) == false) {
            $appTokenKey = getAppTokenKey($token);
            Cache::rm('uniappLogin_' . $appTokenKey);
        } else {
            session('userId', null);
        }
        return true;
    }
    /*------------------------------------------------------ */
    //-- 验证密码强度
    /*------------------------------------------------------ */
    private function checkPwd($pwd)
    {
        $pwd = trim($pwd);
        if (empty($pwd)) {
            return langMsg('密码不能为空.', 'member.checkpwd.empty_pwd');
        }
        if (strlen($pwd) < 8) {//必须大于8个字符
            return langMsg('密码必须大于八字符.', 'member.checkpwd.pwd_length_error');
        }
        if (preg_match("/^[0-9]+$/", $pwd)) { //必须含有特殊字符
//            return langMsg('密码不能全是数字.', 'member.checkpwd.pwd_not_number');
        }
        if (preg_match("/^[a-zA-Z]+$/", $pwd)) {
            return langMsg('密码不能全是字母.', 'member.checkpwd.pwd_not_letter');
        }
        /*if (preg_match("/^[0-9A-Z]+$/", $pwd)) {
            return '请包含数字，字母大小写或者特殊字符';
        }
        if (preg_match("/^[0-9a-z]+$/", $pwd)) {
            return '请包含数字，字母大小写或者特殊字符';
        }*/
        return true;
    }
    /*------------------------------------------------------ */
    //-- 生成用户唯一标识,主要用于分享后身份识别
    /*------------------------------------------------------ */
    public function getToken()
    {
        $token = random_str(16);
        $count = $this->where('token', $token)->count('user_id');
        if ($count >= 1) return $this->getToken();
        return $token;
    }

    /**
     * 会员注册
     * @param array $inArr 写入数据
     *  * @param int $wxuid 微信会员ID
     * @param bool $is_admin 是否是后台添加的用户
     * @param string $obj
     * @return bool|string
     */
    public function register($inArr = array(), $wxuid = 0, $is_admin = false, &$obj = '', $isTrans = true)
    {
        if (empty($inArr['pid'])) {
            $inArr['pid'] = 0;
        }
        $inArr['pid'] = $inArr['pid'] * 1;
        if (empty($inArr)) {
            return '获取注册数据失败.';
        }
        $WeiXinUsersModel = new WeiXinUsersModel();
        if (empty($inArr['openid']) == false && $wxuid < 1 && $inArr['platform'] != 'H5-WX') {
            $openid = $inArr['openid'];
            $wxuid = $WeiXinUsersModel->where('wx_openid', $openid)->value('wxuid');
            if ($wxuid < 1) {
                return '未找到相关微信会员信息.';
            }
            $dataObj = $WeiXinUsersModel->WXBizDataCrypt($inArr['openid'], $inArr['iv'], $inArr['encryptedData']);
            if (is_array($dataObj) == false) {
                return $dataObj;
            }
            $inArr['mobile'] = $dataObj['phoneNumber'];
            unset($inArr['openid'], $inArr['iv'], $inArr['encryptedData']);
        } elseif ($wxuid < 1) {
            if (empty($inArr['mobile'])) {
                return '请填写手机号码';
            }
            if (checkMobile($inArr['mobile']) == false) {
                return '手机号码不正确.';
            }

            $count = $this->where('mobile', $inArr['mobile'])->count('user_id');
            if ($count > 0) return '手机号码：' . $inArr['mobile'] . '，已存在.';
            if (empty($inArr['nick_name']) == false) { //昵称不为空时，判断是否已存在
                $count = $this->where('nick_name', $inArr['nick_name'])->count('user_id');
                if ($count > 0) return '昵称：' . $inArr['nick_name'] . '，已存在.';
            }
            $res = $this->checkPwd($inArr['password']); //验证密码强度
            if ($res !== true) {
                return $res;
            }
            $inArr['password'] = f_hash($inArr['password']);


            if ($is_admin == false && $inArr['pid'] == 0) { //非后台新增会员
                $register_invite_code = settings('register_invite_code');
                $register_must_invite = settings('register_must_invite');
                $share_user_id = 0;
                if ($register_invite_code > 0) {
                    if ($register_must_invite == 1 && empty($inArr['invite_code'])) {
                        return '需要填写邀请信息才能注册.';
                    }
                    if ($register_invite_code == 1 || is_numeric($inArr['invite_code']) == false) { //邀请码
                        $share_user_id = $this->where('token', $inArr['invite_code'])->value('user_id');
                    } else {
                        if ($register_invite_code == 2) { //会员ID
                            $invite_code = $inArr['invite_code'] * 1;
                            $share_user_id = $this->where('user_id', $invite_code)->value('user_id');
                        } elseif ($register_invite_code == 3) { //会员手机号
                            $share_user_id = $this->where('mobile', $inArr['invite_code'])->value('user_id');
                        }
                    }
                }
                //查不到信息，可能用户通过分享二维码进来
                if ($share_user_id < 1) {
                    $share_user_id = $this->where('token', $inArr['invite_code'])->value('user_id');
                }

                if ($share_user_id < 1 && $register_invite_code > 0 && $register_must_invite == 1) {
                    return '邀请帐号不存在.';
                }
                $inArr['pid'] = $share_user_id * 1;
            }

            if (empty($inArr['openid']) == false) {
                $openid = $inArr['openid'];
                $wxUser = $WeiXinUsersModel->where('wx_openid', $openid)->find();
                if (empty($inArr['nick_name'])) {
                    $inArr['nick_name'] = $wxUser['wx_nickname'];
                }
                if (empty($inArr['headimgurl'])) {
                    $inArr['headimgurl'] = $this->getHeadImg($wxUser['wx_headimgurl']);
                }

                if ($wxUser['user_id'] <= 0) {
                    $wxuid = $wxUser['wxuid'];
                }
                unset($inArr['openid']);
                unset($inArr['encryptedData']);
            }
        }

        $time = time();
        $inArr['token'] = $this->getToken();
        $inArr['reg_time'] = $time;
        if ($inArr['pid'] < 1 && $is_admin == false) {
            $inArr['pid'] = $this->returnPid(0, $openid, $inArr['invite_code']);
        }
        unset($inArr['invite_code']);
        unset($inArr['platform']);

        if ($isTrans == true) {
            Db::startTrans();
        }
        $inArr['profit_pid'] = $inArr['pid'];
        $inArr['ld_agnetid'] = $inArr['pid'];
        $res = $this->create($inArr);
        $user_id = $res->user_id;
        if ($user_id < 1) {
            if ($isTrans == true) {
                Db::rollback();
            }
            return '未知错误-1，请尝试重新提交.';
        }
        if ($user_id < 29889) {
            $this->where('user_id', $user_id)->delete();
            $inArr['user_id'] = 29889;
            $res = $this->create($inArr);
            $user_id = $res->user_id;
            if ($user_id < 1) {
                if ($isTrans == true) {
                    Db::rollback();
                }
                return '未知错误-2，请尝试重新提交.';
            }
        }
        //捆绑微信会员信息
        if ($wxuid > 0) {
            $res = $WeiXinUsersModel->bindUserId($wxuid, $user_id);
            if ($res < 1) {
                if ($isTrans == true) {
                    Db::rollback();
                }
                return '捆绑微信会员信息失败.';
            }
        } //end
        if ($isTrans == true) {
            Db::commit();
        }
        //后台添加的用户，加日志
        if ($is_admin && !empty($obj)) {
            $obj->_log($user_id, '后台手动新增会员-用户id:' . $user_id, 'member');
        }
        $this->userId = $user_id;
        //注册会员成功后异步执行
        asynRun('member/UsersModel/asynRunRegister', ['user_id' => $user_id, 'pid' => $inArr['pid']]);
        return true;
    }

    /*------------------------------------------------------ */
    //-- 注册异步处理
    /*------------------------------------------------------ */
    public function asynRunRegister($data)
    {
        $user_id = $data['user_id'];
        $pid = $data['pid'];
        $mkey = 'asynRunRegisterIng' . $user_id;
        $asynRunRegisterIng = Cache::get($mkey);
        if (empty($asynRunRegisterIng) == false) {
            return true;
        }
        Cache::set($mkey, 1, 60);
        //创建会员帐户信息
        $AccountModel = new AccountModel();
        $count = $AccountModel->where('user_id', $user_id)->count();
        if ($count < 1) {
            $res = $AccountModel->createData(['user_id' => $user_id, 'update_time' => time()]);
            if ($res < 1) {
                return '创建会员帐户信息失败.';
            }
        }
        //end
        //注册赠送欢乐豆
        $register_integral = settings('register_integral') * 1;
        if ($register_integral > 0) {
            $changedata['change_desc'] = '注册赠送欢乐豆';
            $changedata['change_type'] = 7;
            $changedata['by_id'] = $user_id;
            $changedata['use_integral'] = $register_integral;
            $changedata['total_integral'] = $register_integral;
            $res = $AccountModel->change($changedata, $user_id, false);
            if ($res < 1) {
                return '注册赠送欢乐豆失败.';
            }
        }
        //end

        $bind_pid_time = settings('bind_pid_time');
        if ($bind_pid_time < 1) {
            //写入关系链
            $this->regUserBind($user_id, $pid);
        }
        //红包模块存在执行
        if (class_exists('app\shop\model\BonusModel')) {
            //注册送红包
            (new \app\shop\model\BonusModel)->sendByReg($user_id);
        }
        return true;
    }

    /*------------------------------------------------------ */
    //-- 返上绑定上级ID
    /*------------------------------------------------------ */
    private function returnPid($user_id = 0, $openid = '', $share_token = '')
    {
        if ($user_id > 0) {
            return $this->where('user_id', $user_id)->value('pid');
        }
        $wxuid = 0;
        if (empty($openid) == false) {
            $wxuid = (new WeiXinUsersModel)->where('wx_openid', $openid)->value('wxuid');
        }
        $pid = 0;
        //分享注册
        if ($wxuid > 0) {//微信访问根据微信分享来源记录，执行
            $bind_share_rule = settings('bind_share_rule');
            if ($bind_share_rule == 0) {//按最先分享绑定
                $sort = 'id ASC';
            } else {//按最后分享绑定
                $sort = 'id DESC';
            }
            $pid = (new \app\weixin\model\WeiXinInviteLogModel)->where('wxuid', $wxuid)->order($sort)->value('user_id');
        } elseif (empty($share_token) == false) {
            $pid = $this->getShareUser($share_token);
        }
        return $pid * 1;
    }

    /*------------------------------------------------------ */
    //-- 找回用户密码
    /*------------------------------------------------------ */
    public function forgetPwd($data = array(), &$obj)
    {
        if (empty($data)) {
            return '获取数据失败.';
        }
        if (empty($data['mobile'])) {
            return '请填写手机号码';
        }
        if (checkMobile($data['mobile']) == false) {
            return '手机号码不正确.';
        }
        $res = $this->checkPwd($data['password']);//验证密码强度
        if ($res !== true) {
            return $res;
        }
        $user = $this->where('mobile', $data['mobile'])->find();
        if (f_hash($data['password']) == $user['password']) {
            return '新密码与旧密码一致,请核实.';
        }
        $upArr['password'] = f_hash($data['password']);
        $res = $this->where('user_id', $user['user_id'])->update($upArr);
        if ($res < 1) return '未知错误，修改会员密码失败.';
        $obj->_log($user['user_id'], '用户找回密码.', 'member');
        return true;
    }
    /*------------------------------------------------------ */
    //-- 修改用户密码
    /*------------------------------------------------------ */
    public function editPwd($data = array(), &$obj)
    {
        if (empty($data)) {
            return '获取数据失败.';
        }
        $res = $this->checkPwd($data['password']);//验证密码强度
        if ($res !== true) {
            return $res;
        }
        $user = $this->where('user_id', $this->userInfo['user_id'])->find();
        $oldPwd = f_hash($data['old_password']);
        if ($oldPwd != $user['password']) {
            return '旧密码错误.';
        }
        $upArr['password'] = f_hash($data['password']);
        if ($upArr['password'] == $user['password']) {
            return '新密码与旧密码一致无须修改.';
        }
        $res = $this->where('user_id', $user['user_id'])->update($upArr);
        if ($res < 1) return '未知错误，修改会员密码失败.';
        $obj->_log($user['user_id'], '用户修改密码.', 'member');
        return true;
    }
    /*------------------------------------------------------ */
    //-- 绑定会员手机
    /*------------------------------------------------------ */
    public function bindMobile($data = array(), &$obj)
    {
        if (empty($data)) {
            return '获取数据失败.';
        }
        $res = $this->checkPwd($data['password']);//验证密码强度
        if ($res !== true) {
            return $res;
        }
        if (is_numeric($data['pay_password']) == false) {
            return '请填写6位数字的支付密码.';
        }
        $count = $this->where('mobile', $data['mobile'])->count('user_id');
        if ($count > 0) {
            return $data['mobile'] . '此手机号码已绑定其它帐号.';
        }
        $upArr['mobile'] = $data['mobile'];
        $upArr['password'] = f_hash($data['password']);
        $upArr['pay_password'] = f_hash($data['pay_password']);
        $res = $this->where('user_id', $this->userInfo['user_id'])->update($upArr);
        if ($res < 1) return '未知错误，绑定手机失败.';
        $obj->_log($this->userInfo['user_id'], '用户绑定手机号码.', 'member');
        return true;
    }
    /*------------------------------------------------------ */
    //-- 获取用户信息
    //-- val 查询值
    //-- type 查询类型
    //-- isCache 是否调用缓存
    /*------------------------------------------------------ */
    public function info($val, $type = 'user_id', $isCache = true)
    {
        if (empty($val)) return false;
        //if ($isCache == true) $info = Cache::get($this->mkey . $val);
        //if (empty($info) == false) return $info;
        if ($type == 'token') {
            $info = $this->where('token', $val)->find();
            if (empty($info)) {
                return [];
            }
            $info = $info->toArray();
        } else {
            $info = $this->where('user_id', $val)->find();
            if (empty($info)) {
                return [];
            }
            $info = $info->toArray();
            $AccountModel = new AccountModel();
            $account = $AccountModel->where('user_id', $val)->find();
            if (empty($account) == true) {
                //创建会员帐户信息
                $AccountModel->save(['user_id' => $val, 'update_time' => time()]);
                $account = $AccountModel->where('user_id', $val)->find();
            }
            $info['account'] = $account->toArray();
        }
        $info['is_has_paypwd'] = 0;//是否已设置支付密码
        if (empty($info['pay_password']) == false) {
            $info['is_has_paypwd'] = 1;
        }
        unset($info['password'], $info['pay_password']);
        $info['region_text'] = '';
        $RegionModel = new \app\mainadmin\model\RegionModel();
        if ($info['district'] > 0) {
            $region = $RegionModel->info($info['district']);
            $info['region_text'] = $region['merger_name'];
        }
        $info['shareUrl'] = config('config.host_path') . '/?share_token=' . $info['token'];//分享链接
        if ($info['role_id'] > 0) {
            $info['role'] = (new DividendRoleModel)->info($info['role_id']);
        }
        if (empty($info['role'])) {
            $info['role']['role_id'] = 0;
            $info['role']['role_name'] = '普通会员';
        }
        if ($info['bank_city'] > 0) {
            $region = $RegionModel->info($info['bank_city']);
            $info['bank_region_text'] = $region['merger_name'];
        }
        //还没有执行绑定关系执行
        if ($info['is_bind'] == 0) {
            $bind_pid_time = settings('bind_pid_time');
            if ($bind_pid_time < 1 || $info['last_buy_time'] > 0) {
                $this->regUserBind($info['user_id'], $info['pid']);
            }
        } //end
//        if ($info['level_id'] > 0) {
//            $info['level_name'] = (new UsersLevelApplyModel)->where('level_id',$info['level_id'])->value('level_name');
//        }

        $info['isRegion'] = 0;
        $info['regionName'] = '';
        if ($info['district_agent'] > 0 || $info['city_agent'] > 0 || $info['province_agent'] > 0) {
            $info['isRegion'] = 1;
            $info['regionName'] .= $info['province_agent'] > 0 ? '省代 ' : '';
            $info['regionName'] .= $info['city_agent'] > 0 ? '市代 ' : '';
            $info['regionName'] .= $info['district_agent'] > 0 ? '区代 ' : '';
        }


        //Cache::set($this->mkey . $val, $info, 30);
        return $info;
    }
    /*------------------------------------------------------ */
    //--获取上级信息
    /*------------------------------------------------------ */
    public function getSuperior($pid)
    {
        if ($pid < 1) return [];
        $info = $this->info($pid);
        unset($info['password']);//销毁不需要的字段
        return $info;
    }
    /*------------------------------------------------------ */
    //--获取会员帐户
    /*------------------------------------------------------ */
    public function getAccount($user_id, $isCache = true)
    {
        $user_id = $user_id * 1;
        if ($user_id < 1) return array();
        $mkey = $this->mkey . 'account_' . $user_id;
        if ($isCache == true) $info = Cache::get($mkey);
        if (empty($info) == false) return $info;
        $info = $this->where('u.user_id', $user_id)->alias('u')->field('u.user_id,u.mobile,ua.*')->join('users_account ua', 'u.user_id = ua.user_id', 'left')->find();
        if (empty($info) == false) {
            $info = $info->toArray();
        }
        Cache::set($mkey, $info, 60);
        return $info;
    }
    /*------------------------------------------------------ */
    //-- 更新会员信息
    /*------------------------------------------------------ */
    public function upInfo($user_id, $data)
    {
        $user_id = $user_id * 1;
        $res = $this->where('user_id', $user_id)->update($data);
        $this->cleanMemcache($user_id);
        return $res;
    }
    /*------------------------------------------------------ */
    //-- 根据token获取分享者进行关联
    //-- $val int/string 用户ID/分享token
    //-- $type string 类型
    /*------------------------------------------------------ */
    public function getShareUser($val = '', $type = 'token')
    {
        if (empty($val)) return 0;
        $DividendSatus = settings('DividendSatus');
        if ($DividendSatus == 0) return 0;//不开启推荐，不执行
        if ($type == 'token') {
            $pInfo = $this->where('token', $val)->find();
        } else {
            $pInfo = $this->where('user_id', $val)->find();
        }
        if (empty($pInfo)) return 0;
        if ($pInfo['is_ban'] == 1) {//如果用户被封禁，直接归被封禁用户的上级
            if ($pInfo['pid'] < 1) return 0;
            return $this->getShareUser($pInfo['pid'], 'user_id');
        }
        return $pInfo['user_id'];
    }
    /*------------------------------------------------------ */
    //-- 获取会员下级汇总
    /*------------------------------------------------------ */
    public function userShareStats($user_id = 0, $isCache = true)
    {
        $info = Cache::get($this->mkey . '_us_' . $user_id);
        if ($isCache == true && empty($info) == false) return $info;
        $user_id = $user_id * 1;
        $UsersBindSuperiorModel = new UsersBindSuperiorModel();
        $levelField = ['pid', 'pid_b', 'pid_c'];
        $info['all'] = 0;
        foreach ($levelField as $key => $field) {
            $where = [];
            $where[$field] = $user_id;
            $count = $UsersBindSuperiorModel->where($where)->count();
            $info[$key + 1] = $count;
            $info['all'] += $count;
        }
        Cache::set($this->mkey . '_us_' . $user_id, $info, 30);
        return $info;
    }
    /*------------------------------------------------------ */
    //-- 操作等级关联
    // -- user_id int 会员ID
    // -- pid  int  所属上级ID 值为-1时，执行查询来源
    // -- is_edit boolean 是否重新修改，不是修改发送绑定消息通知
    /*------------------------------------------------------ */
    public function regUserBind($user_id = 0, $pid = 0, $is_edit = false)
    {
        if ($user_id < 1) return true;
        if ($is_edit == false) {
            $DividendSatus = settings('DividendSatus');
            if ($DividendSatus == 0) return true;//不开启推荐，不执行
            $is_bind = $this->where('user_id', $user_id)->value('is_bind');
            if ($is_bind > 0) return true;//已执行绑定不再执行
            $bingKey = 'regUserBindIng' . $user_id;
            if (empty(Cache::get($bingKey)) == false) {
                return true;
            }
            Cache::set($bingKey, 1, 60);
        }
        if ($pid == -1) {
            $pid = $this->returnPid($user_id);
        }
        $UsersBindSuperiorModel = new UsersBindSuperiorModel();
        //会员上级汇总处理
        $res = $UsersBindSuperiorModel->treat($user_id, $pid, $is_edit);
        if ($res == false) {
            return false;
        }

        if ($is_edit == false) {
            $this->where('user_id', $user_id)->update(['is_bind' => 1]);
            if ($pid < 1) return true;
            //发送模板消息
            $WeiXinMsgTplModel = new \app\weixin\model\WeiXinMsgTplModel();
            $WeiXinUsersModel = new WeiXinUsersModel();
            $wxInfo = $WeiXinUsersModel->info($user_id);
            if (empty($wxInfo['wx_nickname']) == false) {
                $data['user_id'] = $user_id;
                $data['nickname'] = $wxInfo['wx_nickname'];
                $data['sex'] = $wxInfo['sex'] == 1 ? '男' : '女';
                $data['region'] = $wxInfo['wx_province'] . $wxInfo['wx_city'];
                $data['send_scene'] = 'bind_user_msg';
                unset($wxInfo);

                $sendUids[$pid] = 1;
                $usersBind = $UsersBindSuperiorModel->where('user_id', $user_id)->find();
                if ($usersBind['pid_b'] > 0) {
                    $sendUids[$usersBind['pid_b']] = 2;
                }
                foreach ($sendUids as $uid => $val) {
                    $data['level'] = $val;
                    $data['openid'] = $WeiXinUsersModel->where('user_id', $uid)->value('wx_openid');
                    $WeiXinMsgTplModel->send($data);
                }
            }

        }
        return true;
    }
    /*------------------------------------------------------ */
    //-- 获取会员的上级关联链
    /*------------------------------------------------------ */
    public function getSuperiorList($user_id = 0)
    {
        if ($user_id < 1) return array();
        $chain = Cache::get('userSuperior_' . $user_id);
        if ($chain) return $chain;
        $dividendRole = (new DividendRoleModel)->getRows();
        $i = 1;
        $user_id = $this->where('user_id', $user_id)->value('pid');
        if ($user_id < 1) return [];
        do {
            $info = $this->where('user_id', $user_id)->field('user_id,nick_name,pid,role_id,reg_time')->find();
            $chain[$i]['level'] = $i;
            $chain[$i]['user_id'] = $info['user_id'];
            $chain[$i]['reg_time'] = dateTpl($info['reg_time']);
            $chain[$i]['nick_name'] = empty($info['nick_name']) ? '未填写' : $info['nick_name'];
            $chain[$i]['role_name'] = $info['role_id'] > 0 ? $dividendRole[$info['role_id']]['role_name'] : '无身份';
            $user_id = $info['pid'];
            $i++;
        } while ($user_id > 0);

        Cache::set('userSuperior_' . $user_id, $chain, 300);
        return $chain;
    }

    /*------------------------------------------------------ */
    //-- 当前月签到记录
    /*------------------------------------------------------ */
    public function signInfo($user_id = 0)
    {
        $signInfo['signDay'] = [];
        $signInfo['constant'] = 0;
        $signInfo['isSign'] = 0;
        $where[] = ['user_id', '=', $user_id];
        $where[] = ['year', '=', date('Y')];
        $where[] = ['month', '=', date('m') * 1];
        $info = (new UsersSignModel)->where($where)->field('constant_num,month,days,sign_time')->find();
        if (empty($info)) return $signInfo;
        $days = explode(',', $info['days']);
        foreach ($days as $day) {
            $signDay[] = $day * 1;
        }
        $signInfo['signDay'] = $signDay;
        $signInfo['constant'] = $info['constant_num'];
        if (date('d') == date('d', $info['sign_time'])) {
            $signInfo['isSign'] = 1;
        }
        $signInfo['sign_constant'] = settings('sign_constant');
        return $signInfo;
    }


    /*------------------------------------------------------ */
    //-- 签到欢乐豆
    /*------------------------------------------------------ */
    public function signIntegral()
    {
        $use_integral = settings('sign_integral');
        return $use_integral;
    }

    /*------------------------------------------------------ */
    //-- 签到记录
    /*------------------------------------------------------ */
    public function signLog($user_id, $yearMonth)
    {
        $yearMonth = explode('-', $yearMonth);
        $where[] = ['user_id', '=', $user_id];
        $where[] = ['year', '=', $yearMonth[0]];
        $where[] = ['month', '=', $yearMonth[1] * 1];
        $logs = (new UsersSignModel)->where($where)->value('logs');
        if (empty($logs)) {
            return [];
        }
        $logs = json_decode($logs, true);
        return $logs;
    }

    /*------------------------------------------------------ */
    //-- 签到
    /*------------------------------------------------------ */
    public function signIng($user_id = 0)
    {
        $year = date('Y');
        $month = date('n');
        $day = date('d');
        $sign_in = settings('sign_in');
        if ($sign_in == 0) {
            return '签到功能未开启.';
        }
        $sign_integral = settings('sign_integral');
        $sign_constant = settings('sign_constant');
        $mkey = 'SignIng_' . $user_id;
        $status = Cache::get($mkey);
        if (empty($status) == false) {
            return '签到正在处理中...';
        }
        $UsersSignModel = new UsersSignModel();
        $data = $UsersSignModel->where(['user_id' => $user_id, 'year' => $year, 'month' => $month])->find();

        Db::startTrans();
        if (empty($data) == false) {
            $dates = explode(',', $data['days']);
            if (in_array($day, $dates)) {
                Db::rollback();
                Cache::rm($mkey);
                return '今天已经签到,请勿重复签到.';
            }
            $constant_integral = 0;
            //判断是否连接签到
            if (end($dates) == $day - 1) {
                $constant_num = $data['constant_num'] + 1;//连续签到天数+1
                if (isset($sign_constant[$constant_num])) {
                    $constant_integral = $sign_constant[$constant_num]['integral'];
                }
            } else {
                $constant_num = 1;//断续后，重新计算
            }

            $logs = json_decode($data['logs'], true);
            $log['sign_integral'] = $sign_integral;
            $log['constant_integral'] = $constant_integral;
            $total_integral = $sign_integral + $log['constant_integral'];
            $log['total_integral'] = $total_integral;
            $log['constant_num'] = $constant_num;
            $logs[$day] = $log;

            $dates[] = $day;
            //本月数据已有,直接更新
            $upData = ['days' => join(',', $dates), 'constant_num' => $constant_num, 'sign_time' => time()];
            $upData['use_integral'] = ['INC', $log['total_integral']];
            $upData['logs'] = json_encode($logs);
            $res = $UsersSignModel->where(['sign_id' => $data['sign_id'], 'sign_time' => $data['sign_time']])->update($upData);
        } else {
            //本月数据没有,进行插入
            $inData = [
                'user_id' => $user_id,
                'constant_num' => 1,
                'year' => $year,
                'month' => $month,
                'days' => $day,
                'use_integral' => $sign_integral,
                'sign_time' => time()
            ];
            $log['sign_integral'] = $sign_integral;
            $log['constant_integral'] = 0;
            $log['total_integral'] = $sign_integral;
            $log['constant_num'] = 1;
            $total_integral = $sign_integral;
            $logs[$day] = $log;
            $inData['logs'] = json_encode($logs);
            //插入的,用户id,年月存在唯一索引所以不会重复插入
            $res = $UsersSignModel->insert($inData);
        }

        if ($res < 1) {
            Db::rollback();
            Cache::rm($mkey);
            return '签到失败,请重试.';
        }

        //签到成功，加欢乐豆
        $accData['change_desc'] = '签到获得欢乐豆';
        $accData['change_type'] = 10;
        $accData['by_id'] = 0;
        $accData['use_integral'] = $total_integral;
        $res = (new AccountModel)->change($accData, $user_id, false);
        Cache::rm($mkey);
        if (!$res) {
            Db::rollback();
            return '签到失败,欢乐豆处理异常';
        }

        Db::commit();
        $data = [];
        $data['total_integral'] = $total_integral;
        return $data;
    }
    /*------------------------------------------------------ */
    //-- 团队统计
    /*------------------------------------------------------ */
    public function teamCount($user_id = 0)
    {
        if ($user_id < 1) return 0;
        $where[] = ['', 'exp', Db::raw("FIND_IN_SET('" . $user_id . "',superior)")];
        return (new UsersBindSuperiorModel)->where($where)->count() - 1;
    }
    /*------------------------------------------------------ */
    //-- 获取远程会员头像到本地
    /*------------------------------------------------------ */
    public function getHeadImg($headimgurl = '')
    {
        if (empty($headimgurl) == false && strstr($headimgurl, 'http')) {
            $headimgurl = strstr($headimgurl, 'https') ? str_replace("https", "http", $headimgurl) : $headimgurl;
            $file_path = config('config._upload_') . 'headimg/' . substr($this->userInfo['user_id'], -1) . '/';
            makeDir($file_path);
            //图片文件
            $file_name = $file_path . random_str(12);
            $extend = getFileExtend($headimgurl);
            $file_name .= '.' . $extend[1];
            downloadImage($headimgurl, $file_name);
            $upArr['headimgurl'] = $headimgurl = trim($file_name, '.');
            $this->upInfo($this->userInfo['user_id'], $upArr);
        }
        return '.' . $headimgurl;
    }
    /*------------------------------------------------------ */
    //-- 获取分享二维码
    /*------------------------------------------------------ */
    public function getMyQrCode($goods_id = 0)
    {
        $file_path = config('config._upload_') . 'qrcode/h5/';
        makeDir($file_path);
        if ($goods_id > 0) {
            $value = config('config.host_path') . '/pages/shop/goods/info?goods_id=' . $goods_id . '&share_token=' . $this->userInfo['token'];
        } else {
            $value = config('config.host_path') . '?share_token=' . $this->userInfo['token'];
        }
        $file = $file_path . md5($value) . '_' . $this->userInfo['user_id'] . '.png';
        if (file_exists($file) == true) {
            return $file;
        }

        include EXTEND_PATH . 'phpqrcode/phpqrcode.php';//引入PHP QR库文件
        $QRcode = new \phpqrcode\QRcode();
        $QRcode::png($value, $file, "L", 10, 1, 2, true);
        return $file;
    }
    /*------------------------------------------------------ */
    //-- 获取用户小程序二维码
    /*------------------------------------------------------ */
    public function getUserMiniQrcode($goods_id = 0)
    {
        $page = '';
        if ($goods_id > 0) {
            $page = 'pages/shop/goods/info';
        }
        $file_path = config('config._upload_') . 'qrcode/wxmp/';
        $imageName = md5($page . '_' . $goods_id) . '_' . $this->userInfo['user_id'] . '.jpg';
        $imageSrc = $file_path . "/" . $imageName; //图片名字

        if (file_exists($imageSrc) == true) {
            return $imageSrc;
        }

        $scene = $this->userInfo['token'] . '_' . $goods_id;
        $mini = new \app\weixin\model\WeiXinMpModel();
        $qrcode = $mini->get_qrcode($page, $scene);
        if (strstr($qrcode, ",")) {
            $qrcode = explode(',', $qrcode);
            $qrcode = $qrcode[1];
        }
        makeDir($file_path);

        file_put_contents($imageSrc, base64_decode($qrcode));//返回的是字节数

        return $imageSrc;
    }
    /*
     * 获取用户用户名
     */
    public function getUsernameByuid($userid){
        if(empty($userid)){
            return '';
        }
        $res = Db::table('users')->where('user_id',$userid)->find();
        if($res){
            return $res['nick_name'];
        }else{
            return '';
        }
    }
     /**
     * 设置团队上级Id及等级
     * @param $user_id
     * @param $ld_agentid
     * @return void
     *
     */
    public function setBindLadderAgentUser($user_id=0,$ld_agentid=0){
        if($user_id>0 && $ld_agentid>0){
            return $this->Model->where(['user_id'=>$user_id])->update(['ld_agnetid'=>$ld_agentid]);
        }

    }

    /**
     * 添加团结奖励及升级
     * @param $ld_agentid
     * @param $ordermoney
     * @param $userid
     * @return void
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     *
     */
    public function addLdGrade($orderinfo=[]){
        if(empty($orderinfo)){
            return ;
        }

        $ordermoney = $orderinfo['order_amount'];
        $ordersn = $orderinfo['order_sn'] ;
        $orderId = $orderinfo['order_id'] ;
        $userid = $orderinfo['user_id'] ;
        $actionlock = cache::get('addLdGrade_'.$ordersn);
        if($actionlock){
            return false;
        }
        $childUserInfo = $this->where(['user_id'=>$userid])->field('user_id,nick_name,ld_agnetid')->find()->toArray();
        if(!$childUserInfo) return;
        $ld_agentid = $childUserInfo['ld_agnetid'];
        $list = $this->field('user_id,ld_agnetid,ld_grade')->order('ld_grade','desc')->select()->toarray();

        $return =array_reverse($this->getParentIds($ld_agentid,$list));
        //改变数组的key值
        $pai_flag = 2;
        if(count($return) ==1) $pai_flag=1;
        $basic_ld_grade = config("config.ld_grade_level");
        if($return){
            foreach ($return as $key=>$value){

                $jietuArr = (array_slice($return,$key+1));
                // var_dump($jietuArr);exit;
                $thisUserInfo = $this->where(['user_id'=>$value])->find()->toArray();//查询是否有该用户
                $userUpdateData = [];//需要修改用户的数组

                if($thisUserInfo){
                    $tj_arr = ['daili'=>0,'fwzx'=>0,'fgs'=>0,'lqgd'=>0,'grade'=>0];
                    $t1 = ($this->getAllLowerLevelId($list,$value));//获取当前用户所有下级（user_id）

                    $tj_arr['daili']=count($t1);
                    $tj_arr['fwzx']=($this->where('user_id','in',$t1)->where(['ld_grade'=>1])->count());
                    $tj_arr['fgs']=($this->where('user_id','in',$t1)->where(['ld_grade'=>2])->count());
                    $tj_arr['lqgd']=($this->where('user_id','in',$t1)->where(['ld_grade'=>3])->count());
                    $getUserLadderSettingGrade= $this->getUserLadderSettingGrade($tj_arr);//获取对应的等级和返点比例
                    // var_dump($getUserLadderSettingGrade);exit;
                    $tj_arr['grade']=$getUserLadderSettingGrade['grade'];
                    if($tj_arr['grade']>0 ){
                            if($tj_arr['grade'] > $thisUserInfo['ld_grade']){//如果当前的等级大于用户原本等级，则修改
                                    $userUpdateData['ld_grade'] = $tj_arr['grade'];
                            }

                    }
                    $realBl = $this->getRealLadderAwardBl($jietuArr,$thisUserInfo,$pai_flag);//获取用户的真实的分成比例
                    // var_dump($realBl);exit;
                    $tj_arr['realbl'] = $realBl;
                    $tj_arr['user_id'] = $value;

                    $rrs1 = true;
                    $rrs2 = true;
                    $rrs3 = true;
                    // $RedisLockKey = 'RedisLock_addLdGrade_'.$value;
                    if($tj_arr['realbl']['flag'] == 1){//可分成
                        $userUpdateData['ld_money'] = bcadd($thisUserInfo['ld_money'], bcdiv((bcmul($ordermoney,$tj_arr['realbl']['bl'],2)),100,2),2);
                        $add_log = [];
                        $add_log['user_id']=$value;
                        $add_log['from_user_id']=$userid;
                        $add_log['order_id']=$orderId;
                        $add_log['money']= bcdiv((bcmul($ordermoney,$tj_arr['realbl']['bl'],2)),100,2);
                        if( $thisUserInfo['ld_grade']== 3){
                            $miaos='分红';
                        }elseif( $thisUserInfo['ld_grade']== 2){
                            $miaos='团队奖';
                        }elseif( $thisUserInfo['ld_grade']== 1){
                            $miaos='见单奖';
                        }else{
                            $miaos='服务奖';
                        }
                        $add_log['remark']=$miaos.' - 下级【'.$userid.'-'.$childUserInfo['nick_name'].'】购买加盟区产品，订单编号【'.$ordersn.'】，获得'. $add_log['money']." ".$miaos.'奖励';
                        $add_log['grades'] = $basic_ld_grade[$thisUserInfo['ld_grade']];
                        $add_log['grade']=$thisUserInfo['ld_grade'];
                        $add_log['sn'] = $ordersn;;
                        $add_log['status'] = $orderinfo['order_status'];


                        $rrs2 =  $this->addLadderLog($add_log);
                        $rrs3 = $this->upUserAccount($value,$add_log['money'],$orderId, $add_log['remark']);

                    }
                    if($userUpdateData){

                        $rrs1 = $this->where(['user_id'=>$value])->update($userUpdateData);
                    }


//                    if ($redisLock->lockByLua($RedisLockKey)) {
//
//                        if($rrs1){
//                            $redisLock->unlock($RedisLockKey);
//                        }else{
//                            continue;
//                        }
//
//                    }
                }

            }
        }
       cache::set('addLdGrade_'.$ordersn,1,500);

    }
    public function upUserAccount($userid=0,$amount=0.00,$orderId=0,$remark=''){
        if($userid >0){
            try{
                Db::startTrans();
                $wallet = Db::name("users_account")->where(['user_id'=>$userid])->find();
                $upd['balance_money'] =bcadd($wallet['balance_money'],$amount,2);
                $upd['update_time'] =$_SERVER['REQUEST_TIME'];
                $res =  Db::name('users_account_log')->where(['user_id'=>$userid,'change_type'=>11,'by_id'=>$orderId])->count();
//                $res =  true;
                if(!$res){
                    $changedata['change_desc'] = $remark;
                    $changedata['change_type'] = 11;
                    $changedata['by_id'] = $orderId;
                    $changedata['balance_money'] = $amount;
                    $changedata['md5log'] = strtolower(md5('user_id_'.$userid.'_order_'.$orderId.'_11'));

                    $res1 = (new AccountModel)->change($changedata, $userid, false);
                    if($res1){
                        Db::commit();
                        return true;
                    }
                    Db::rollback();
                    return false;
                }
                Db::rollback();
                return false;
            }catch (Exception $e){
                Db::rollback();
                return false;
            }
        }
        return false;
    }
    public function addLadderLog($add){
        $add['addtime'] = time();
        $hasLog =  Db::name('main_user_ladder_reward_log')->where(['order_id'=>$add['order_id'],'user_id'=>$add['user_id']])->count();
        if($hasLog)return false;
        return Db::name('main_user_ladder_reward_log')->insertGetId($add);
    }

    //获取所有下级
    function getAllLowerLevelId($list, $p_id = '0', $isFirstTime = true)
    {
        static $arr = [];
        if ($isFirstTime) {
            $arr = [];
        }
        foreach ($list as $key => $val) {
            if ($val['ld_agnetid'] == $p_id) {
                $arr[]           = $val['user_id'];
                $this->getAllLowerLevelId($list, $val['user_id'], false);
            }
        }
        return $arr;
    }


    /**获取所有父级
     * @param $id
     * @param $list
     * @param $parents
     * @return array|mixed
     */
    function getParentIds($id, $list,$parents = [])
    {


        //改变数组的key值
        $list = array_column($list, NULL, 'user_id');
//        var_dump($list[$id]);exit;
        if(!isset($list[$id])) {
            return [];
        }
        $parents[] =(string) $id;
        $info = $list[$id];
        if ($info['ld_agnetid'] == 0) {
            return $parents;
        }
        return $this->getParentIds($info['ld_agnetid'], $list, $parents);
    }

    /**
     * 获取当前用户的团队最新等级
     * @param $param
     * @return int
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     *
     */
    function getUserLadderSettingGrade($param){
        $return=['grade'=>0,'bl'=>0];

        $row = Db::name('main_ladder')->find(1);

        if($row){


            if($row['la_gd_daili_num']<= $param['daili'] && $row['la_gd_fgs_num'] <= $param['fgs']){
                $return['grade'] = 3;
                $return['bl'] = $row['la_gd_jd_bl'];
                return $return;
            }else if($row['la_fgs_daili_num']<= $param['daili'] && $row['la_fgs_fwzx_num'] <= $param['fwzx']){
                $return['grade'] = 2;
                $return['bl'] = $row['la_fgs_jd_bl'];

                return $return;
            }else if($row['la_fwzx_daili_num']<= $param['daili'] ){
                $return['grade'] = 1;
                $return['bl'] = $row['la_fwzx_jd_bl'];

                return $return;
            }
        }
        return $return;
    }

    /**
     * 获取用户的真实的分成比例
     * @param $ids
     * @param $user
     * @return int[]
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    function getRealLadderAwardBl($ids,$user,$flag){

        $return = ['bl'=>0,'flag'=>2];//flag 2:不可分钱 ，1：可分钱

        if( $user){
            $grade  = $user['ld_grade'];
            if($grade >0){
                $row = Db::name('main_ladder')->find(1);
                $count3 = $this->where('user_id','in',$ids)->where(['ld_grade'=>3])->count();
                $count2 = $this->where('user_id','in',$ids)->where(['ld_grade'=>2])->count();
                $count1 = $this->where('user_id','in',$ids)->where(['ld_grade'=>1])->count();
                // var_dump($count1);
                //  var_dump($count2);
                //  var_dump($count3);
                //  var_dump($grade);
                //  var_dump($user['user_id']);
                if($flag ==1){
                    if($grade== 3){
                            $return['bl'] = ($row['la_gd_jd_bl']);
                            $return['flag'] = 1;

                            return $return;

                }else if($grade== 2){
                            $return['bl'] = ($row['la_fgs_jd_bl']);
                            $return['flag'] = 1;
                            return $return;

                }else if($grade== 1){
                        $return['bl'] = ($row['la_fwzx_jd_bl']);
                        $return['flag'] = 1;
                        return $return;

                }
                }else{

                 }

                if($grade== 3){
                    if($count3){
                        $return['flag'] = 2;
                        return $return;
                    }else{
                        if($count2){
                            $return['bl'] = bcsub($row['la_gd_jd_bl'],$row['la_fgs_jd_bl'],2);
                            $return['flag'] = 1;
                        }else{
                            if($count1){
                                $return['bl'] = bcsub($row['la_gd_jd_bl'],$row['la_fwzx_jd_bl'],2);
                                $return['flag'] = 1;
                            }else{

                                $return['bl'] = ($row['la_gd_jd_bl']);
                                $return['flag'] = 1;
                            }
                        }
                        return $return;
                    }
                }else if($grade== 2){
                    if($count2){
                        $return['flag'] = 2;
                        return $return;
                    }else{
                        if($count1){
                            $return['bl'] = bcsub($row['la_fgs_jd_bl'],$row['la_fwzx_jd_bl'],2);
                            $return['flag'] = 1;
                        }else{
                            $return['bl'] = ($row['la_fgs_jd_bl']);
                            $return['flag'] = 1;
                        }
                        return $return;
                    }
                }else if($grade== 1){
                    if($count1){
                        $return['flag'] = 2;
                        return $return;
                    }else{
                        $return['bl'] = ($row['la_fwzx_jd_bl']);
                        $return['flag'] = 1;
                        return $return;
                    }
                }
            }
        }
        return $return;
    }



}
